package com.xiaobai.frame.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xiaobai.common.utils.SnowFlow;
import com.xiaobai.common.utils.TokenUtil;
import com.xiaobai.common.utils.config.page.Pager;
import com.xiaobai.common.utils.result.R;
import com.xiaobai.common.utils.result.Result;
import com.xiaobai.common.utils.result.ResultCode;
import com.xiaobai.common.utils.tool.AuthUtil;
import com.xiaobai.common.utils.tool.CheckUtil;
import com.xiaobai.common.utils.tool.EncryptionUtil;
import com.xiaobai.common.utils.tool.Func;
import com.xiaobai.common.utils.tool.StringUtils;
import com.xiaobai.data.manager.system.RoleManager;
import com.xiaobai.data.manager.system.UserDeptManager;
import com.xiaobai.data.manager.system.UserManager;
import com.xiaobai.data.manager.system.UserRoleManager;
import com.xiaobai.frame.service.IUserService;
import com.xiaobai.frame.utils.RedisTool;
import com.xiaobai.model.dto.system.userDTO.UserInfo;
import com.xiaobai.model.entity.system.Role;
import com.xiaobai.model.entity.system.User;
import com.xiaobai.model.entity.system.UserDept;
import com.xiaobai.model.entity.system.UserRole;
import com.xiaobai.model.vo.system.login.LoginVO;
import io.jsonwebtoken.Claims;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.xiaobai.common.utils.TokenUtil.ACCESS_EXPIRE;
import static com.xiaobai.common.utils.TokenUtil.REFRESH_EXPIRE;
import static com.xiaobai.frame.utils.RedisKey.REFRESH_TOKEN;
import static com.xiaobai.frame.utils.UserInfoKey.INITIAL_PASSWORD;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-06-07
 */
@Service
@AllArgsConstructor
public class UserServiceImpl implements IUserService {
    private final RedisTool redisTool;
    private final UserManager userManager;
    private final UserDeptManager userDeptManager;
    private final RoleManager roleManager;
    private final UserRoleManager userRoleManager;
    @Override
    public Result addUserInfo(UserInfo userInfo) throws Exception {
        if (Func.isEmpty(userInfo)) {
            return R.fail(ResultCode.PARAMETER_NULL,"请求参数为空");
        }
        if (!CheckUtil.checkAccount(userInfo.getAccount())) {
            return R.fail(ResultCode.PRECONDITION_FAILED,"账号位数不在6到15位之间");
        }
        User one = userManager.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount, userInfo.getAccount()), false);
        if (Func.isNotEmpty(one)) {
            return R.fail(ResultCode.SAME_RESOURCES,"该账号已注册,请重试");
        }
//        注册之后统一密码
        userInfo.setPassword(EncryptionUtil.encryption(INITIAL_PASSWORD));
        User user = new User();
        BeanUtils.copyProperties(userInfo, user);
        SnowFlow snowFlow = new SnowFlow(1, 2);
        long nextId = snowFlow.nextId();
        user.setId(nextId);
        if (!StringUtils.isEmpty(user.getDeptId())) {
//            添加用户部门关系表
            UserDept userDept = new UserDept();
            userDept.setUserId(nextId).setDeptId(Long.valueOf(user.getDeptId()));
            userDeptManager.save(userDept);
        }
        if (StringUtils.isNotBlank(user.getRoleId())) {
            Role one1 = roleManager.getOne(new LambdaQueryWrapper<Role>().eq(Role::getId, user.getRoleId()), false);
            if (Func.isNull(one1)) {
                return R.fail(ResultCode.NOT_SEEK_RESOURCE, "传入角色数据未查询到");
            }
            UserRole userRole = new UserRole();
            userRole.setUserId(nextId).setRoleId(Long.valueOf(user.getRoleId()));
            userRoleManager.save(userRole);
        }
        if (userManager.save(user)) {
            return R.success(ResultCode.SUCCESS_CREATE_RESOURCE, "注册成功");
        } else {
            return R.fail(ResultCode.INTERNAL_SERVER_ERROR, "注册失败请,联系管理人员");
        }
    }

    @Override
    public Result login(String account, String password) {
        if (Func.isNull(account) || Func.isNull(password)) {
            return R.fail(ResultCode.PARAMETER_NULL, "登录所包含参数缺失");
        }
        User one = userManager.getOne(new LambdaQueryWrapper<User>()
            .eq(User::getAccount, account), false);
        if (Func.isEmpty(one)) {
            return R.fail(ResultCode.NOT_SEEK_RESOURCE, "没有查询到对应账号相关数据");
        }
        if (!EncryptionUtil.checkPassword(password, one.getPassword())) {
            return R.fail(ResultCode.CODE_FAIL, "密码错误,登录失败");
        }
        String refreshToken = TokenUtil.generateRefreshToken(JSON.parseObject(JSON.toJSONString(one)));
        LoginVO loginVO = new LoginVO(TokenUtil.generateAccessToken(JSON.parseObject(JSON.toJSONString(one))),
            refreshToken,ACCESS_EXPIRE);
        redisTool.setCacheObject(REFRESH_TOKEN+one.getId(), refreshToken, REFRESH_EXPIRE, TimeUnit.SECONDS);
        return R.success(ResultCode.SUCCESS, "登录成功", loginVO);
    }

    @Override
    public Result refreshToken(String refreshToken) {
        Claims claims = TokenUtil.parseClaims(refreshToken);
        if (Func.isNull(claims)) {
            return R.fail(ResultCode.UNAUTHORIZED, "刷新令牌异常请重新登录");
        }
        String id = (String) claims.get("id");
        Object cacheObject = redisTool.getCacheObject(REFRESH_TOKEN + id);
        if (Func.isNull(cacheObject) || !Func.equals(cacheObject, refreshToken)) {
            return R.fail(ResultCode.NOT_SEEK_RESOURCE, "刷新令牌异常请重新登录");
        }
        redisTool.deleteObject(REFRESH_TOKEN + id);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", id);
        jsonObject.put("roleId", claims.get("roleId"));
        jsonObject.put("deptId", claims.get("deptId"));
        String accessToken = TokenUtil.generateAccessToken(jsonObject);
        redisTool.setCacheObject(REFRESH_TOKEN + id, accessToken, REFRESH_EXPIRE, TimeUnit.SECONDS);
        LoginVO loginVO = new LoginVO(TokenUtil.generateAccessToken(jsonObject), accessToken, ACCESS_EXPIRE);
        return R.success("刷新成功", loginVO);
    }

    @Override
    public Result logout() {
        String id = String.valueOf(AuthUtil.getId());
        if (redisTool.deleteObject(REFRESH_TOKEN+id)) {
            return R.success(ResultCode.SUCCESS, "登出成功");
        }else {
            return R.fail(ResultCode.INTERNAL_SERVER_ERROR,"登出异常请重试");
        }
    }

    @Override
    public Result resetPassword(String ids) throws Exception {
        if (Func.isNull(ids)) {
            return R.fail(ResultCode.PARAMETER_NULL, "传入数据为空");
        }
        List<String> list = Arrays.asList(ids.split(","));
        boolean update = userManager.update(new LambdaUpdateWrapper<User>().in(User::getId, list)
            .set(User::getPassword, EncryptionUtil.encryption(INITIAL_PASSWORD)));
        if (update) {
            return R.success(ResultCode.SUCCESS_CREATE_RESOURCE, "修改成功");
        }else {
            return R.fail(ResultCode.INTERNAL_SERVER_ERROR, "修改异常,请联系管理人员");
        }
    }

    @Override
    public Result updateUserInfo(User user) throws Exception {
        if (Func.isEmpty(user)) {
            return R.fail(ResultCode.PARAMETER_NULL, "传入数据为空");
        }
        if (!StringUtils.isBlank(user.getPassword())) {
            user.setPassword(EncryptionUtil.encryption(user.getPassword()));
        }
        boolean update = userManager.update(user, new LambdaUpdateWrapper<User>().eq(User::getId, user.getId()));
        if (update) {
            return R.success(ResultCode.SUCCESS_CREATE_RESOURCE,"修改成功");
        }else {
            return R.fail(ResultCode.INTERNAL_SERVER_ERROR,"修改失败,请联系管理人员");
        }
    }

    @Override
    public Result getUserInfo() {
        User one = userManager.getOne(new LambdaQueryWrapper<User>().eq(User::getId, AuthUtil.getId()), false);
        if (Func.isEmpty(one)) {
            return R.fail(ResultCode.NOT_SEEK_RESOURCE, "未查询到对应角色信息,请联系管理人员");
        }
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(one, userInfo);
        return R.success("查询成功",userInfo);
    }

    @Override
    public boolean deleteLogic(List<Long> list) {
        if (Func.isEmpty(list)) {
            return false;
        }
        return userManager.deleteLogic(list);
    }

    @Pager
    @Override
    public Object listUserInfo() {
        return userManager.list();
    }
}
